package com.tiancheng.trade.merchant.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tiancheng.trade.commom.core.data.PageInfo;
import com.tiancheng.trade.commom.core.enums.SettleRuleTypeEnums;
import com.tiancheng.trade.commom.web.model.request.OrderMerchantSettleReqVO;
import com.tiancheng.trade.commom.web.model.response.SettlementRuleResVO;
import com.tiancheng.trade.merchant.dto.requestdto.MerchantSettleRuleRequestDTO;
import com.tiancheng.trade.merchant.enums.MerchantSettleRuleCycleTypeEnum;
import com.tiancheng.trade.merchant.enums.MerchantSettleRuleStatusEnum;
import com.tiancheng.trade.merchant.enums.SettlementTypeEnum;
import com.tiancheng.trade.merchant.mapper.MerchantMapper;
import com.tiancheng.trade.merchant.mapper.MerchantSettleRuleMapper;
import com.tiancheng.trade.merchant.model.Merchant;
import com.tiancheng.trade.merchant.model.MerchantSettleRule;
import com.tiancheng.trade.merchant.service.IMerchantSettleRuleService;
import com.tiancheng.trade.merchant.util.cache.MerchantCache;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * @author kellen
 * @date 2021/7/15
 */
@Service
public class MerchantSettleRuleService extends ServiceImpl<MerchantSettleRuleMapper, MerchantSettleRule>
        implements IMerchantSettleRuleService {

    @Autowired
    private MerchantSettleRuleMapper ruleMapper;
    @Autowired
    private MerchantMapper merchantMapper;
    @Resource
    private MerchantCache merchantCache;

    /**
     * 增 - 新增即生效，同时把旧规则失效
     *
     * @param rule {@link MerchantSettleRule}
     * @return {@link Boolean}
     */
    @Transactional
    @Override
    public Boolean addRule(MerchantSettleRule rule) {
        // 1、查询生效的旧规则
        QueryWrapper<MerchantSettleRule> searchWrapper = new QueryWrapper<>();
        searchWrapper.eq("merchant_code", rule.getMerchantCode());
        searchWrapper.eq("org_payment_channel_id",rule.getOrgPaymentChannelId());
        searchWrapper.eq("rule_status", MerchantSettleRuleStatusEnum.EFFECTIVE.getValue());
        List<MerchantSettleRule> oldRules = ruleMapper.selectList(searchWrapper);

        // 2、若有生效的旧规则，修改状态为“作废”，记录“规则失效时间”，记录最后操作人信息
        if (CollectionUtils.isNotEmpty(oldRules)) {
            oldRules.forEach(d -> {
                d.setRuleStatus(MerchantSettleRuleStatusEnum.INVALIDATION.getValue());
                d.setExpireDate(LocalDateTime.now());
                //d.injectionLastUpdBy();
            });
            this.updateBatchById(oldRules, oldRules.size());
            merchantCache.delCachePaymentSettleRule("M",rule.getMerchantCode());
        }

        // 3、将新增的规则设置为“生效”，生成“规则编号”，记录创建人、更新人，插入数据库
        rule.setRuleStatus(MerchantSettleRuleStatusEnum.EFFECTIVE.getValue());
        rule.setRuleCode(UUID.randomUUID().toString().replace("-", ""));
//        rule.injectionCreatedBy();
//        rule.injectionLastUpdBy();

        return ruleMapper.insert(rule) > 0;
    }

    @Override
    public PageInfo<MerchantSettleRule> queryPage(MerchantSettleRuleRequestDTO ruleRequestDTO) {
        QueryWrapper<MerchantSettleRule> queryWrapper = new QueryWrapper<MerchantSettleRule>() {{
            if (StringUtils.isNotEmpty(ruleRequestDTO.getMerchantCode())) {
                eq("merchant_code", ruleRequestDTO.getMerchantCode());
            }
            if (StringUtils.isNotEmpty(ruleRequestDTO.getRuleCode())) {
                eq("rule_code", ruleRequestDTO.getRuleCode());
            }
            if (null != ruleRequestDTO.getRuleStatus()) {
                eq("rule_status", ruleRequestDTO.getRuleStatus());
            }
        }};
        queryWrapper.orderByDesc("id");
        PageInfo<MerchantSettleRule> pageInfo = this.ruleMapper.find(queryWrapper, (int) ruleRequestDTO.getCurrentPage(), ruleRequestDTO.getPageSize());
        if (pageInfo.getPagination().getTotal() > 0) {
            List<String> merchantCods = pageInfo.getList().stream().map(MerchantSettleRule::getMerchantCode).collect(Collectors.toList());
            List<Merchant> merchants = merchantMapper.getMerchantByMerCode(merchantCods);
            pageInfo.getList().forEach(m -> {
                merchants.stream().filter(merchant -> m.getMerchantCode().equals(merchant.getMerchantCode())).findFirst().ifPresent(one -> {
                    m.setMerchantName(one.getMerchantName());
                    m.setSettlementType(SettlementTypeEnum.getDesc(one.getSettlementType()));
                });
            });
        }
        return pageInfo;
    }

    @Override
    public List<SettlementRuleResVO> findByMerchantCodes(List<String> merchantCodes) {
        QueryWrapper<MerchantSettleRule> condition = new QueryWrapper<>();
        condition.eq("rule_status", MerchantSettleRuleStatusEnum.EFFECTIVE.getValue());
        condition.in("merchant_code", merchantCodes);
        List<MerchantSettleRule> merchantSettleRules = this.baseMapper.selectList(condition);
        return merchantSettleRules2MerchantRuleQueryResVos(merchantSettleRules);
    }

    @Override
    public List<SettlementRuleResVO> queryOrderMerchantSettleRule(OrderMerchantSettleReqVO orderMerchantSettleReqVO) {
        QueryWrapper<MerchantSettleRule> condition = new QueryWrapper<>();
        condition.eq("rule_status", MerchantSettleRuleStatusEnum.EFFECTIVE.getValue());
        condition.eq("org_payment_channel_id", orderMerchantSettleReqVO.getOrgPaymentChannelId());
        condition.in("merchant_code", orderMerchantSettleReqVO.getMerchantCods());
        List<MerchantSettleRule> merchantSettleRules = this.baseMapper.selectList(condition);
        return merchantSettleRules2MerchantRuleQueryResVos(merchantSettleRules);
    }

    private List<SettlementRuleResVO> merchantSettleRules2MerchantRuleQueryResVos(List<MerchantSettleRule> merchantSettleRules){
        if(CollectionUtils.isNotEmpty(merchantSettleRules)){
            // 查询商户清分类型
            return merchantSettleRules.stream().map(rule -> {
                final SettlementRuleResVO vo = new SettlementRuleResVO();
                vo.setSettleRuleCode(rule.getRuleCode());
                vo.setSettleRuleType(SettleRuleTypeEnums.merchant.getCode());
                vo.setMerchantCode(rule.getMerchantCode());
                // 结算类型：1:清分 2:自营，3：平台
                vo.setSettlementType("1");
                vo.setClearingCycleMode(this.getClearingCycleMode(rule.getCycleType()));
                vo.setClearingCycleValue(Integer.parseInt(rule.getCycleValue()));
                if(rule.getCycleType().equals(MerchantSettleRuleCycleTypeEnum.MONTH.getValue())){
                    // 加一个月
                    vo.setClearingCycleValue(1);
                    vo.setClearingCycleValueExt(Integer.parseInt(rule.getCycleValue()));
                }
                // 清分规则(1:百分比 2:平台固定金额 3:商户固定金额)
                vo.setClearingRule("1");
                vo.setPlatformPre(rule.getPlatformPercent());
                return vo;
            }).collect(Collectors.toList());
        }
        return null;
    }
    @Override
    public void deleteByCode(String code) {
        if(StringUtils.isEmpty(code)){
            return;
        }
        MerchantSettleRule d = new MerchantSettleRule();
        d.setRuleStatus(MerchantSettleRuleStatusEnum.INVALIDATION.getValue());
        d.setExpireDate(LocalDateTime.now());
        d.injectionLastUpdBy();
        final QueryWrapper<MerchantSettleRule> condition = new QueryWrapper<>();
        condition.eq("rule_code",code);
        final MerchantSettleRule merchantSettleRule = this.ruleMapper.selectOne(condition);
        merchantCache.delCachePaymentSettleRule("M",merchantSettleRule.getMerchantCode());
        d.setId(merchantSettleRule.getId());
        this.updateById(d);

    }

    @Override
    public List<SettlementRuleResVO> findByMerchantRuleCodes(List<String> merchantRuleCods) {
        QueryWrapper<MerchantSettleRule> condition = new QueryWrapper<>();
        //condition.eq("rule_status", MerchantSettleRuleStatusEnum.EFFECTIVE.getValue());
        condition.in("rule_code", merchantRuleCods);
        List<MerchantSettleRule> merchantSettleRules = this.baseMapper.selectList(condition);
        return merchantSettleRules2MerchantRuleQueryResVos(merchantSettleRules);
    }

    @Override
    public MerchantSettleRule currentRule(String merchantCode, Long orgPaymentChannelId) {
        final List<MerchantSettleRule> rules = this.list(new LambdaQueryWrapper<MerchantSettleRule>().eq(MerchantSettleRule::getMerchantCode, merchantCode)
                .eq(MerchantSettleRule::getOrgPaymentChannelId, orgPaymentChannelId).eq(MerchantSettleRule::getRuleStatus, 1));
        return CollectionUtils.isNotEmpty(rules)?rules.get(0):null;
    }

    /**
     * 清分周期类型，1-天，2-月
     * @param cycleType
     * @return
     */
    private String getClearingCycleMode(String cycleType){
        if(cycleType.equals(MerchantSettleRuleCycleTypeEnum.DAY.getValue())){
         return "1";
        }
        if(cycleType.equals(MerchantSettleRuleCycleTypeEnum.MONTH.getValue())){
            return "2";
        }
        return null;
    }
}
